package com.hrg.wms.service;

import ch.qos.logback.classic.Logger;
import com.hrg.wms.constant.LEDConstants;
import com.hrg.wms.domain.LedDefInfo;
import com.hrg.wms.domain.LedItemDetail;
import com.hrg.wms.domain.LedErrorInfo;
import com.hrg.wms.domain.LedTaskInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import com.onbon.bxk.*;
import org.springframework.util.ObjectUtils;

/**
 * @author shenzq
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class LedShowService {

    private BxArea createContainerArea(LedTaskInfo ledTaskInfo){
        String containerCode = ledTaskInfo.getContainerCode();
        String str = "容器号:"+containerCode;
        byte id = 1;
        short x = 0;
        short y = 1;
        short w = 160;
        short h = 16;
        BxAreaDynamic area = null;
        byte[] data;

        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createContainerArea:"+e.getMessage(),e);
        }
        return area;
    }

    private BxArea createInOutTypeArea(LedTaskInfo ledTaskInfo){
        String type = ledTaskInfo.getInOutType().equals(LEDConstants.TASK_IN_YPE) ? "入库":"出库";
        byte id = 2;
        short x = 160;
        short y = 1;
        short w = 100;
        short h = 16;
        String str = "类型:"+type;
        BxAreaDynamic area = null;
        byte[] data;

        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createInOutTypeArea:"+e.getMessage(),e);
        }
        return area;
    }
    private BxArea createLocationArea(LedTaskInfo ledTaskInfo){
        String locationCode = "";
        if(ledTaskInfo.getInOutType().equals(LEDConstants.TASK_IN_YPE)){
            locationCode = ledTaskInfo.getTagLocationCode();
        }
        if(ledTaskInfo.getInOutType().equals(LEDConstants.TASK_OUT_TYPE)){
            locationCode = ledTaskInfo.getSrcLocationCode();
        }
        byte id = 3;
        short x = 0;
        short y = 25;
        short w = 150;
        short h = 16;
        String str = "货位号:"+locationCode;
        BxAreaDynamic area = null;
        byte[] data;
        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createLocationArea:"+e.getMessage(),e);
        }
        return area;
    }

    private BxArea createStationArea(LedTaskInfo ledTaskInfo){

        byte id = 4;
        short x = 160;
        short y = 25;
        short w = 145;
        short h = 16;
        String str = "";
        if(ledTaskInfo.getInOutType().equals(LEDConstants.TASK_IN_YPE)){
            str = "入口:"+ ledTaskInfo.getSrcLocationCode();
        }
        if(ledTaskInfo.getInOutType().equals(LEDConstants.TASK_OUT_TYPE)){
            str = "出口:"+ ledTaskInfo.getTagLocationCode();
        }

        BxAreaDynamic area = null;
        byte[] data;

        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createStationArea:"+e.getMessage(),e);
        }
        return area;
    }
    private BxArea createTaskNoArea(LedTaskInfo ledTaskInfo){
        byte id = 5;
        short x = 0;
        short y = 51;
        short w = 255;
        short h = 16;
        BxAreaDynamic area = null;
        String remark = "";
        if(ledTaskInfo.getInOutType().equals(LEDConstants.TASK_OUT_TYPE)){
            // 出库货载时，才拼接 备注信息
            if(ledTaskInfo.getRemark() != null && !"".equals(ledTaskInfo.getRemark())){
                remark = ledTaskInfo.getRemark();
            }
        }
        String str = "任务号:"+ ledTaskInfo.getTaskNo()+" "+remark;
        byte[] data;
        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createTaskNoArea:"+e.getMessage(),e);
        }
        return area;

    }


    private BxArea createItemArea(LedTaskInfo ledTaskInfo){
        byte id = 6;
        short x = 1;
        short y = 75;
        short w = 255;
        short h = 16;
        BxAreaDynamic area = null;
        List<LedItemDetail> detailList = ledTaskInfo.getDetailList();
        StringBuffer sb = new StringBuffer();
        sb.append("物料描述:");
        detailList.forEach(itemDetail -> {
            if(itemDetail.getUnitName() != null){
                sb.append(itemDetail.getItemName())
                        .append(" ")
                        .append(itemDetail.getQty().stripTrailingZeros().toPlainString())
                        .append(" "+itemDetail.getUnitName())
                        .append(",");
            }else{
                sb.append(itemDetail.getItemName())
                        .append(" ")
                        .append(itemDetail.getQty().stripTrailingZeros().toPlainString())
                        .append(" ")
                        .append(",");
            }
        });
        byte[] data;
        try {
            String itemStr = sb.toString();
            // 去掉最后一个逗号
            itemStr = itemStr.substring(0,itemStr.length() -1);
            System.out.println(itemStr);
            data = itemStr.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            // area.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x05);
            // 设置停留时间
            area.setHoldTime((byte) 3);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createItemArea:"+e.getMessage(),e);
        }
        return area;
    }


    private BxArea createErrorTrayNumArea(LedErrorInfo ledErrorInfo){
        String containerCode = ledErrorInfo.getContainerCode();
        String str = "容器号:"+containerCode;
        byte id = 8;
        short x = 70;
        short y = 5;
        short w = 240;
        short h = 16;
        BxAreaDynamic area = null;
        byte[] data;

        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createErrorTrayNumArea:"+e.getMessage(),e);
        }
        return area;
    }

    private BxArea creatErrorCheckArea(LedErrorInfo ledErrorInfo){
        String checkResult = ledErrorInfo.getCheckResult().equals(LEDConstants.CHECK_RESULT_SUCCESS) ? "成功":"失败";
        String str = "校验结果:"+checkResult;
        byte id = 9;
        short x = 70;
        short y = 30;
        short w = 240;
        short h = 16;
        BxAreaDynamic area = null;
        byte[] data;

        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("creatErrorCheckArea:"+e.getMessage(),e);
        }
        return area;
    }

    private BxArea createErrorMsgArea(LedErrorInfo ledErrorInfo){
        String errorMsg = ledErrorInfo.getErrorMsg();
        String str = "原因:"+errorMsg;
        byte id = 0;
        short x = 0;
        short y = 55;
        short w = 255;
        short h = 16;
        BxAreaDynamic area = null;
        byte[] data;

        try {
            data = str.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            area = new BxAreaDynamic(id, x, y, w, h, data, true);
            // 语音模式
            //area2.setSoundMode((byte) 0x02);
            // 人声模式
            area.setSoundPerson((byte) 0x00);
            // 重复次数
            area.setSoundRepeat((byte) 0x03);
            // 发音速度
            area.setSoundSpeed((byte) 0x02);
            // 音量
            area.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area.setDispMode((byte) 0x01);
            // 设置停留时间
            area.setHoldTime((byte) 0);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("createErrorMsgArea:"+e.getMessage(),e);
        }
        return area;
    }
    /**
     * 切换时，必须先删除上一个的 areaId，否则显示回重合
     * @param ledTaskInfo
     */
    public void clearArea(LedTaskInfo ledTaskInfo) throws IOException {
        // 删除 前面的区域Id
        BxCmdSendDynamicArea delArea = new BxCmdSendDynamicArea(null);
        byte[] areaId;
        areaId = new byte[]{1,2,3,4,5,6,7,8,9,0};
        delArea.setDelAreaIds(areaId);
        BxDataPack delDatePack = new BxDataPack(delArea);
        byte[] delSeq = delDatePack.pack();

        Socket client = new Socket();
        String ip = ledTaskInfo.getIp();
        int port = ledTaskInfo.getPort();
        SocketAddress address = new InetSocketAddress(ip, port);
        OutputStream out = null;
        InputStream in = null;
        try {
            client.connect(address, 3000);
            client.setSoTimeout(3000);
            out = client.getOutputStream();
            in = client.getInputStream();

            out.write(delSeq);
            byte[] resp = new byte[1024];
            int len = in.read(resp);
            BxResp bxResp = BxResp.parse(resp, len);
            if(bxResp.isAck()) {
                System.out.println("删除区域成功!");
            }
            else {
                System.out.println("区域删除 fail !");
            }

        } catch (IOException e) {
            e.printStackTrace();
            log.error("clearArea:"+e.getMessage(),e);
        }finally {
            if(out != null){
                out.close();
            }
            if(in != null){
                in.close();
            }
            if(client != null){
                client.close();
            }
        }
    }
    public void showTaskInfo(LedTaskInfo ledTaskInfo) throws IOException {
        this.clearArea(ledTaskInfo);

        List<BxArea> areaList = new ArrayList<BxArea>();
        BxArea containerArea = this.createContainerArea(ledTaskInfo);
        BxArea inOutTypeArea = this.createInOutTypeArea(ledTaskInfo);
        BxArea locationArea = this.createLocationArea(ledTaskInfo);
        BxArea stationArea = this.createStationArea(ledTaskInfo);
        BxArea taskNoArea = this.createTaskNoArea(ledTaskInfo);
        BxArea itemArea = this.createItemArea(ledTaskInfo);
        areaList.add(containerArea);
        areaList.add(inOutTypeArea);
        areaList.add(locationArea);
        areaList.add(stationArea);
        areaList.add(taskNoArea);
        areaList.add(itemArea);


        BxCmd cmd = new BxCmdSendDynamicArea(areaList);
        BxDataPack dataPack = new BxDataPack(cmd);
        byte[] seq = dataPack.pack();

        Socket client = new Socket();
        String ip = ledTaskInfo.getIp();
        int port = ledTaskInfo.getPort();
        SocketAddress address = new InetSocketAddress(ip, port);
        OutputStream out = null;
        InputStream in = null;
        try {
            client.connect(address, 3000);
            client.setSoTimeout(3000);
            out = client.getOutputStream();
            in = client.getInputStream();

            out.write(seq);
            byte[] resp = new byte[1024];
            int len = in.read(resp);
            BxResp bxResp = BxResp.parse(resp, len);
            if(bxResp.isAck()) {
                System.out.println("Well done!!");
            }
            else {
                System.out.println("I am sorry!");
            }

        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }finally {
            if(out != null){
                out.close();
            }
            if(in != null){
                in.close();
            }
            if(client != null){
                client.close();
            }
        }
    }


    public void showErrorInfo(LedErrorInfo ledErrorInfo) throws IOException {
        LedTaskInfo ledTaskInfo = new LedTaskInfo();
        ledTaskInfo.setIp(ledErrorInfo.getIp());
        ledTaskInfo.setPort(ledErrorInfo.getPort());
        this.clearArea(ledTaskInfo);
        List<BxArea> areaList = new ArrayList<BxArea>();
        BxArea errorTrayNumArea = this.createErrorTrayNumArea(ledErrorInfo);
        BxArea checkArea = this.creatErrorCheckArea(ledErrorInfo);
        BxArea errorMsgArea = this.createErrorMsgArea(ledErrorInfo);
        areaList.add(errorTrayNumArea);
        areaList.add(checkArea);
        areaList.add(errorMsgArea);

        BxCmd cmd = new BxCmdSendDynamicArea(areaList);
        BxDataPack dataPack = new BxDataPack(cmd);
        byte[] seq = dataPack.pack();

        Socket client = new Socket();
        String ip = ledTaskInfo.getIp();
        int port = ledTaskInfo.getPort();
        SocketAddress address = new InetSocketAddress(ip, port);
        OutputStream out = null;
        InputStream in = null;
        try {
            client.connect(address, 3000);
            client.setSoTimeout(3000);
            out = client.getOutputStream();
            in = client.getInputStream();

            out.write(seq);
            byte[] resp = new byte[1024];
            int len = in.read(resp);
            BxResp bxResp = BxResp.parse(resp, len);
            if(bxResp.isAck()) {
                System.out.println("show error Well done!!");
            }
            else {
                System.out.println("show error I am sorry!");
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
        }finally {
            if(out != null){
                out.close();
            }
            if(in != null){
                in.close();
            }
            if(client != null){
                client.close();
            }
        }
    }

    public void showDefInfo(LedDefInfo ledDefInfo) throws IOException {
        LedTaskInfo ledTaskInfo = new LedTaskInfo();
        ledTaskInfo.setIp(ledDefInfo.getIp());
        ledTaskInfo.setPort(ledDefInfo.getPort());
        this.clearArea(ledTaskInfo);
        List<BxArea> areas = new ArrayList<BxArea>();
        // 创建区域1
        byte id = 7;
        short x = 65;
        short y = 32;
        short w = 140;
        short h = 32;
        // 前面的 FO001 字库卡对应的字体幸好
        String s1 = "\\FO001" + ledDefInfo.getDefStr();
        byte[] data1;

        try {
            data1 = s1.getBytes("gb2312");
            //五代K卡最后一个参数给true、非5代的给false
            BxAreaDynamic area1 = new BxAreaDynamic(id, x, y, w, h, data1, true);
            // 人声模式
            area1.setSoundPerson((byte) 0x00);
            // 重复次数
            area1.setSoundRepeat((byte) 0x03);
            // 发音速度
            area1.setSoundSpeed((byte) 0x02);
            // 音量
            area1.setSoundVolume((byte) 10);
            // 要发声的文字，仅在 soundMode = 0x02时有效
            //area2.setSoundData(soundData);

            //
            // 显示方式，其定义如下：
            // 0x01——静止显示
            // 0x02——快速打出
            // 0x03——向左移动
            // 0x04——向右移动
            // 0x05——向上移动
            // 0x06——向下移动
            // 设置显示方式为 0x03 - 向左移动
            area1.setDispMode((byte) 0x01);
            // 设置停留时间
            area1.setHoldTime((byte) 0);
            areas.add(area1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            log.error("创建显示区域异常："+e.getMessage(),e);
        }

        //
        // 创建一个发送动态区命令
        BxCmd cmd = new BxCmdSendDynamicArea(areas);
        // 对命令进行封装
        BxDataPack dataPack = new BxDataPack(cmd);
        // 生成命令序列
        byte[] seq = dataPack.pack();

        //
        // 创建 Socket
        Socket client = new Socket();
        //
        String ip = ledTaskInfo.getIp();;
        int port = ledTaskInfo.getPort();
        // 创建 socket 地址
        SocketAddress address = new InetSocketAddress(ip, port);
        OutputStream out = null;
        InputStream in = null;
        try {
            //
            // 建立 TCP 连接
            client.connect(address, 3000);
            //
            // 设置读超时时间
            client.setSoTimeout(3000);

            //
            // 创建输出流
            out = client.getOutputStream();
            //
            // 创建输入流
            in = client.getInputStream();
            out.write(seq);
            //
            // 回读返回帧
            byte[] resp = new byte[1024];
            int len = in.read(resp);

            //
            // parse
            BxResp bxResp = BxResp.parse(resp, len);

            //
            // 判断命令是否被正确执行
            if(bxResp.isAck()) {
                System.out.println("Well done!!");
            }
            else {
                System.out.println("I am sorry!");
            }


        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage(),e);
            throw new RuntimeException(" 显示默认信息异常："+e.getMessage());
        }finally {
            if(out != null){
                out.close();
            }
            if(in != null){
                in.close();
            }
            if(client != null){
                client.close();
            }
        }
    }
}
